package scfg.output.database;

import java.io.File;
import java.util.*;
import java.util.Map.Entry;

import scfg.*;
import scfg.output.*;
import scfg.utils.*;

public class CtFileAggregator {
	
	public static String parseSubClass(String filename) {
		if (filename == null) 
			throw new IllegalArgumentException();
		String[] arr = filename.toLowerCase().split("\\.");
		char c = arr[2].charAt(0);
		switch (c) {
		case 'a' : return "Archaea";
		case 'b' : return "Bacteria";
		case 'c' : return "Eukaryota";
		case 'e' : return "Eukaryota (C)";
		case 'm' : return "Eukaryota (M)";
		default :
			return null;
		}
	}
	
	public static String parseClass(String filename) {
		if (filename == null) 
			throw new IllegalArgumentException();
		String[] arr = filename.split("\\.");
		char c = arr[1].charAt(0);
		switch (c) {
		case '5' : return "5S";
		case '1' : return "16S";
		case '2' : return "23S";
		case 't' : return "tRNA";
		default :
			return null;
		}
	}
	
	public static List<DBAccessionNumberPair> processAccessionNums(String accessionNums) {
		List<DBAccessionNumberPair> rtnList = new LinkedList<DBAccessionNumberPair>();
		if (accessionNums == null)
			return rtnList;
		String[] arr = accessionNums.split(" ");
		for(String s : arr) {
			if (s.length() > 1)
				rtnList.add(new DBAccessionNumberPair(s));
		}
		return rtnList;
	}
	
	public static void processFile(File file) {
		if (file == null || !file.exists() || !file.isFile())
			throw new IllegalArgumentException();
		RNAFormattedFile rnaff = StructureAggregator.convertCtFile(file, new RNAFormattedFile("none"));
		if (rnaff == null)
			return;
		String accessionNum = null;
		try {
			Scanner scan = new Scanner(file);
			while(scan.hasNext() && accessionNum == null) {
				String line = scan.nextLine();
				if (line.matches("\\s*[Aa]ccession ?[Nn]umbers?:?\\s+.*"))
					accessionNum = line.replaceAll("\\s*[Aa]ccession ?[Nn]umbers?:?\\s+", "").trim();
			}
			scan.close();
		} catch (Exception e) {
		}
		HashMap<String, String> values = new HashMap<String, String>();
		values.put("sequence", rnaff.get("seq"));
		values.put("name", file.getName());
		values.put("rnaClass", parseClass(file.getName()));
		values.put("rnaSubClass", parseSubClass(file.getName()));
		List<DBAccessionNumberPair> accessionNumbers = processAccessionNums(accessionNum);
		HashMap<String, Integer> countsMap = KHGrammar.getCountsArray(rnaff.get("nat"));
		double dense = (double)countsMap.get("NBP") * 2.0 / (double)countsMap.get("seqlength");
		values.put("dense", dense + "");
		// TODO: dense comp? need MFE
		AlignedSequence alnseq = new AlignedSequence(values, null, accessionNumbers);
		alnseq.addStructure(new RnaAlgoPrediction("refrence", rnaff.get("nat")));
		int result = DatabaseHandler.insertAlignedSequence(alnseq);
		if (result == -99)
			System.err.println("Illegal Arguement Exception");
		else if (result == -98)
			System.err.println("The sequence already exists in the database.");
	}
	
	public static void processCtDir(String dirname){
		processCtDir(new File(dirname));
	}
	
	public static void processCtDir(File base) {
		if (base == null || !base.exists() || !base.isDirectory())
			throw new IllegalArgumentException();
		File[] files = base.listFiles(new NOPCTFilter());
		int count = 0;
		for(File f : files) {
			System.out.println((++count) + "/" + files.length + " :: " + f.getName());
			if (f.isFile())
				processFile(f);
			else if (f.isDirectory()) {
				// Do Nothing
			}
		}
	}
	
	public static void processFastaFile(String filename) {
		processFastaFile(new File(filename));
	}
	
	public static void processFastaFile(File file) {
		Map<String, List<String>> alignments = alnFastaParser.parseFastaFile(file.getAbsolutePath());
		int count = 0;
		for (Entry<String, List<String>> me : alignments.entrySet()) {
			if ((count++)%150 == 0)
				System.out.println((count-1) + "/" + alignments.size());
			List<AlignedSequence> sequences = DatabaseHandler.getSequencesByAccessionNumber(me.getKey());
			seqLoop:
			for(AlignedSequence alnSeq : sequences) {
				for (int i=0;i<me.getValue().size();i++) {
					if (me.getValue().get(i).replaceAll("-", "").equals(alnSeq.getSequence())) {
						alnSeq.setAlignment(me.getValue().get(i));
						DatabaseHandler.updateAlignedSequence(alnSeq);
						CSVWriter.append(alnSeq.getRnaClass(), alnSeq.getDenseString());
						break seqLoop;
					}
				}
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		CSVWriter.addWriter("5S");
//		CSVWriter.addWriter("16S");
//		CSVWriter.addWriter("23S");
//		CSVWriter.append("5S", "5S_Dense");
//		CSVWriter.append("16S", "16S_Dense");
//		CSVWriter.append("23S", "23S_Dense");
		
		String filename = "/home/david/Documents/RNA/ct_files/5S";
//		processCtDir(filename);
//		filename = "/home/david/Documents/RNA/ct_files/16S";
//		processCtDir(filename);
		filename = "/home/david/Documents/RNA/ct_files/23S";
		processCtDir(filename);
//		filename = "/home/david/Documents/RNA/fasta_alignments/5S/5S.T.alnfasta";
//		processFastaFile(filename);
//		filename = "/home/david/Documents/RNA/fasta_alignments/16S/16S.T.alnfasta";
//		processFastaFile(filename);
		filename = "/home/david/Documents/RNA/fasta_alignments/23S/23S.T.alnfasta";
		processFastaFile(filename);
		
//		CSVWriter.finalizeWriter("5S");
//		CSVWriter.finalizeWriter("16S");
//		CSVWriter.finalizeWriter("23S");
		
		System.out.println("\n\n" + Display.box("Done...", "\t"));
	}

}
